home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
iconv8_s.arc
/
ICONT.ARC
/
LINK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-28
|
10KB
|
382 lines
/*
* link.c -- linker main program that controls the linking process.
*/
#include "..\h\config.h"
#include "general.h"
#include "tproto.h"
#include "globals.h"
#include "link.h"
#include "..\h\paths.h"
#include "..\h\header.h"
#ifdef Header
#include "hdr.h"
#ifndef MaxHeader
#define MaxHeader MaxHdr
#endif /* MaxHeader */
#endif /* Header */
/*
* Prototype.
*/
hidden novalue setexe Params((char *fname));
/*
* The following code is operating-system dependent [@link.01]. Include
* system-dependent files and declarations.
*/
#if PORT
/* nothing to do */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || VM || VMS
/* nothing to do */
#endif /* AMIGA || ATARI_ST || HIGHC_386 ... */
#if MSDOS
#if MICROSOFT || TURBO
#include <fcntl.h>
#endif /* MICROSOFT || TURBO */
#endif /* MSDOS */
#if MVS
char *routname; /* real output file name */
#endif /* MVS */
#if OS2
#if MICROSOFT
#include <fcntl.h>
#endif /* MICROSOFT */
#endif /* OS2 */
#if UNIX
#ifdef CRAY
#define word word_fubar
#include <sys\types.h>
#include <sys\stat.h>
#undef word
#else /* CRAY */
#include <sys\types.h>
#include <sys\stat.h>
#endif /* CRAY */
#endif /* UNIX */
/*
* End of operating-system specific code.
*/
FILE *infile; /* input file (.u1 or .u2) */
FILE *outfile; /* interpreter code output file */
#ifdef DeBugLinker
FILE *dbgfile; /* debug file */
static char dbgname[MaxFileName]; /* debug file name */
#endif /* DeBugLinker */
char inname[MaxFileName]; /* input file name */
static char icnname[MaxFileName]; /* icon source file name */
struct lfile *llfiles = NULL; /* List of files to link */
#ifdef EvalTrace
int colmno = 0; /* current source program colm number */
#endif /* EvalTrace */
int lineno = 0; /* current source program line number */
int fatals = 0; /* number of errors encountered */
/*
* ilink - link a number of files, returning error count
*/
int ilink(ifiles,outname)
char **ifiles;
char *outname;
{
int i;
struct lfile *lf,*lfls;
char *filename; /* name of current input file */
linit(); /* initialize memory structures */
while (*ifiles)
alsolink(*ifiles++); /* make initial list of files */
/*
* Phase I: load global information contained in .u2 files into
* data structures.
*
* The list of files to link is maintained as a queue with llfiles
* as the base. lf moves along the list. Each file is processed
* in turn by forming .u2 and .icn names from each file name, each
* of which ends in .u1. The .u2 file is opened and globals is called
* to process it. When the end of the list is reached, lf becomes
* NULL and the loop is terminated, completing phase I. Note that
* link instructions in the .u2 file cause files to be added to list
* of files to link.
*/
for (lf = llfiles; lf != NULL; lf = lf->lf_link) {
filename = lf->lf_name;
makename(inname, SourceDir, filename, U2Suffix);
makename(icnname, TargetDir, filename, SourceSuffix);
#if MVS || VM
/*
* Even though the ucode data is all reasonable text characters, use
* of text I/O may cause problems if a line is larger than LRECL.
* This is likely to be true with any compiler, though the precise
* disaster which results may vary.
*/
infile = fopen(inname, ReadBinary);
#else
infile = fopen(inname, ReadText);
#endif /* MVS || VM */
if (infile == NULL)
quitf("cannot open %s",inname);
readglob();
fclose(infile);
}
/* Phase II: resolve undeclared variables and generate code. */
/*
* Open the output file.
*/
#ifdef WATERLOO_C_V3_0
strcat(outname," (BIN");
#endif /* WATERLOO_C_V3_0 */
#if MVS
routname = outname;
outfile = tmpfile(); /* write icode to temporary file to
avoid fseek-PDS limitations */
#else /* MVS */
outfile = fopen(outname, WriteBinary);
#endif /* MVS */
/*
* The following code is operating-system dependent [@link.02]. Set
* untranslated mode if necessary.
*/
#if PORT
/* probably nothing */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || MVS || UNIX || VM || VMS
/* nothing to do */
#endif /* AMIGA || ATARI_ST || ... */
#if MSDOS
#if LATTICE
fmode(outfile,1); /* set for untranslated mode */
#endif /* LATTICE */
#if MICROSOFT || TURBO
setmode(fileno(outfile),O_BINARY); /* set for untranslated mode */
#endif /* MICROSOFT || TURBO */
#endif /* MSDOS */
#if OS2
#if MICROSOFT
setmode(fileno(outfile),O_BINARY);
#endif /* MICROSOFT */
#endif /* OS2 */
/*
* End of operating-system specific code.
*/
if (outfile == NULL)
quitf("cannot create %s",outname);
#ifdef Header
/*
* Open Header, which contains the start-up program and copy it to the
* output file. Then, write out null bytes to past the end of the
* start-up program.
*/
{
int hsize;
char hname[MaxFileName];
char hdrdat[MaxHeader+1];
#if MACINTOSH
#if MPW
{ /* Look for header in same directory as the linker */
char *p, *rindex();
p = (char *)getenv("Command");
if (p) {
strcpy(hname,p);
p = rindex(hname,':') + 1;
}
else
p = hname;
strcpy(p,HeaderPath);
fprintf(stderr,HeaderPath);
fflush(stderr);
}
#endif /* MPW */
#endif /* MACINTOSH */
fwrite(iconxhdr, sizeof(char), MaxHeader, outfile);
}
#endif /* Header */
for (i = sizeof(struct header); i--;)
putc(0, outfile);
fflush(outfile);
if (ferror(outfile) != 0)
quit("unable to write to icode file");
#ifdef DeBugLinker
/*
* Open the .ux file if debugging is on.
*/
if (Dflag) {
makename(dbgname, TargetDir, llfiles->lf_name, ".ux");
dbgfile = fopen(dbgname, WriteText);
if (dbgfile == NULL)
quitf("cannot create %s", dbgname);
}
#endif /* DeBugLinker */
/*
* Loop through input files and generate code for each.
*/
lfls = llfiles;
while (lf = getlfile(&lfls)) {
filename = lf->lf_name;
makename(inname, SourceDir, filename, U1Suffix);
makename(icnname, TargetDir, filename, SourceSuffix);
#if MVS || VM
infile = fopen(inname, ReadBinary);
#else /* MVS || VM */
infile = fopen(inname, ReadText);
#endif /* MVS || VM */
if (infile == NULL)
quitf("cannot open %s", inname);
gencode();
fclose(infile);
}
gentables(); /* Generate record, field, global, global names,
static, and identifier tables. */
fclose(outfile);
lmfree();
if (fatals > 0)
return fatals;
setexe(outname);
return 0;
}
/*
* lwarn - issue a linker warning message.
*/
novalue lwarn(s1, s2, s3)
char *s1, *s2, *s3;
{
fprintf(stderr, "%s: ", icnname);
if (lineno)
fprintf(stderr, "Line %d # :", lineno);
fprintf(stderr, "\"%s\": %s%s\n", s1, s2, s3);
fflush(stderr);
}
/*
* lfatal - issue a fatal linker error message.
*/
novalue lfatal(s1, s2)
char *s1, *s2;
{
fprintf(stderr, "%s: ", icnname);
if (lineno)
fprintf(stderr, "Line %d # : ", lineno);
fprintf(stderr, "\"%s\": %s\n", s1, s2);
fatals++;
}
/*
* setexe - mark the output file as executable
*/
static novalue setexe(fname)
char *fname;
{
/*
* The following code is operating-system dependent [@link.03]. It changes the
* mode of executable file so that it can be executed directly.
*/
#if PORT
/* something is needed */
Deliberate Syntax Error
#endif /* PORT */
#if AMIGA
/* not necessary */
#endif /* AMIGA */
#if ATARI_ST || MSDOS || MVS || OS2 || VM || V